package rpc

import (
	"context"
	"fmt"

	"gitee.com/hexug/devcloud/mcenter/apps/endpoint"
	"gitee.com/hexug/devcloud/mcenter/apps/permission"
	"gitee.com/hexug/devcloud/mcenter/apps/token"
	"gitee.com/hexug/devcloud/mcenter/apps/user"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
)

type ClientSet struct {
	Conf *Config
	Conn *grpc.ClientConn
}

func NewClient(conf *Config) (*ClientSet, error) {
	ctx, cancel := context.WithTimeout(context.TODO(), conf.Timeout())
	defer cancel()
	ch := make(chan struct{}, 1)
	var (
		conn *grpc.ClientConn
		err  error
	)
	go func(ct context.Context, workDone chan struct{}) {
		conn, err = grpc.DialContext(
			ct,
			conf.Address,
			grpc.WithTransportCredentials(insecure.NewCredentials()),
			//添加中间件
			grpc.WithPerRPCCredentials(conf),
		)
		workDone <- struct{}{}
	}(ctx, ch)
	select { //下面的case只执行最早到来的那一个
	case <-ch:
		if err != nil {
			return nil, err
		}
		return &ClientSet{
			Conf: conf,
			Conn: conn,
		}, nil
	case <-ctx.Done(): //ctx.Done()是一个管道，context超时或者调用了cancel()都会关闭这个管道，然后读操作就会立即返回
		return nil, fmt.Errorf("连接服务端 %s 超时", conf.Address)
	}
}

// token部分的客户端
func (c *ClientSet) Token() token.RPCClient {
	return token.NewRPCClient(c.Conn)
}

// user部分的客户端
func (c *ClientSet) User() user.RPCClient {
	return user.NewRPCClient(c.Conn)
}

// endpoint部分的客户端
func (c *ClientSet) Endpoint() endpoint.RPCClient {
	return endpoint.NewRPCClient(c.Conn)
}

// 权限校验部分
func (c *ClientSet) Permission() permission.RPCClient {
	return permission.NewRPCClient(c.Conn)
}
